import org.grailsext.annotation.Privileged
import org.grailsext.util.Utils

class UserController extends BaseController{

	def beforeInterceptor = [action:this.&auth, except:['login','authenticate','logout']]

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]


    def index = {
        redirect(action: "list", params: params)
    }


	def login = {
		println "Redirect to user login page"
		render(view:'login')
	}

	def authenticate = {
		println "Authenticate user login"
		User u = User.findByUserName(params.userName)
		if(!params.userName && !params.password){
			println "user name or password is not filled"
			flash.message = "Please input user name and password"
			redirect(action:'login')
			return
		}
		if(!u){
			println "No such user"
			flash.message = "No such user: ${params.userName}"
			redirect(action:'login')
			return
		}
		if(u && u.password && u.password != params.password){
			println "Password wrong"
			flash.message = "Your password is not correct"
			redirect(action:'login')
			return
		}
		// Login success
		session.userId = u.id
		session.userName = u.userName
		session.department = u.department
		session.nickName = u.firstName
		println "${u.userName} login success"
		println "originalRequestParams=${session.originalRequestParams}"
		def controller = session.originalRequestParams?.controller?:'answer'
		def action = session.originalRequestParams?.action?:'makeVote'
		Map redirectParams = session.originalRequestParams?:[qstireId:1, questionId:1]
		println "redirectParams=${redirectParams}"
		//		redirect([controller:'answer', action:'makeVote', params:[qstireId:1, questionId:1]])
		redirect(controller:controller, action:action, params:redirectParams)
	}

	def logout = {
		println "user ${session.userName} logout"
		session.userId = null
		session.userName = null
		session.department = null
		session.nickName = null
		render(view:'login')
	}

    def list = {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [userInstanceList: User.list(params), userInstanceTotal: User.count()]
    }

	@Privileged(privileges = ['CREATE_USER'])
    def create = {
        def userInstance = new User()
        userInstance.properties = params
        return [userInstance: userInstance, departmentMap: departmentMap]
    }

	@Privileged(privileges = ['CREATE_USER'])
    def save = {
		println "UserController.save-->"
		println "params: ${params}"
        def userInstance = new User(params)
		// Check user level
		if(userInstance && userInstance.userName == "admin") {
			flash.message = "Administrator can't be changed"
			redirect(action: "list")
			return
		}
		// Selected roles
		def roleIds = Utils.convertStrings2Longs(params.selectedRoles)
		println roleIds
		if(roleIds){
			def criteria = Role.createCriteria()
			def roles = criteria.list{'in'('id', roleIds)}
			println roles
			for(r in roles){
				println "Attach Role to User: " + r
				userInstance.addToRoles(r)
			}
		} else {
			println "Role IDs: " + roleIds
		}

        if (userInstance.save(flush: true)) {
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])}"
            redirect(action: "show", id: userInstance.id)
        }
        else {
            render(view: "create", model: [userInstance: userInstance])
        }
		println "<--UserController.save"
    }

	@Privileged(privileges = ['CREATE_USER'])
    def createall = {
		//TODO
        def userInstance = new User()
        userInstance.properties = params
        return [userInstance: userInstance, departmentMap: departmentMap]
    }

	@Privileged(privileges = ['CREATE_USER'])
    def saveall = {
		//TODO
		println "UserController.saveall-->"
		println "params: ${params}"



		// Selected roles
		def roleIds = Utils.convertStrings2Longs(params.selectedRoles)
		println roleIds
		def roles
		if(roleIds){
			def criteria = Role.createCriteria()
			roles = criteria.list{'in'('id', roleIds)}
			println roles
		} else {
			println "Role IDs: " + roleIds
		}

		// Parse user infos
		boolean hasErrors = false
		String[] userInfos = org.apache.commons.lang.StringUtils.splitByWholeSeparator(params.userInfos, "\r\n")
		for(String ss:userInfos){
			if(org.apache.commons.lang.StringUtils.isEmpty(ss)) {
				continue
			}
			String[] s = org.apache.commons.lang.StringUtils.split(ss, " \t")
			if(s.length != 2) {
				continue
			}
			def userInstance = new User(params)
			userInstance.userName = s[0].trim()
			userInstance.firstName = s[1].trim()
			for(r in roles){
				println "Attach Role to User: " + r
				userInstance.addToRoles(r)
			}
			if (userInstance.save(flush: true)) {
				flash.message = "${message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])}"
			} else {
				hasErrors = true
			}
		}
		if(hasErrors) {
			redirect(action: "list")
		} else {
			render(view: "createall", model: [userInfos: params.userInfos])
		}
		println "<--UserController.save"
	}


	@Privileged(privileges = ['SHOW_USER'])
	def show = {
		def userInstance = User.get(params.id)
		if (!userInstance) {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
			redirect(action: "list")
		}
		else {
			[userInstance: userInstance]
		}
	}

	@Privileged(privileges = ['UPDATE_USER'])
	def edit = {
		def userInstance = User.get(params.id)
		if (!userInstance) {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
			redirect(action: "list")
		}
		else {
			return [userInstance: userInstance, departmentMap: departmentMap]
		}
	}

	@Privileged(privileges = ['UPDATE_USER'])
	def update = {
		println "UserController.update-->"
		println "params: ${params}"
		def userInstance = User.get(params.id)
		if (userInstance) {
			if (params.version) {
				def version = params.version.toLong()
				if (userInstance.version > version) {
					userInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'user.label', default: 'User')] as Object[], "Another user has updated this User while you were editing")
					render(view: "edit", model: [userInstance: userInstance])
					return
				}
			}
			// Password is no change
			if(params.password == '******'){
				params.remove("password")
			}
			userInstance.properties = params
			// Selected roles
			String[] selectedRoles;
			println params.selectedRoles
			if(params.selectedRoles == null){
				userInstance.roles = null
			} else {
				if(params.selectedRoles instanceof String){
					selectedRoles = [params.selectedRoles]
				} else {
					selectedRoles = params.selectedRoles
				}
				println selectedRoles
				println selectedRoles.length
				if(selectedRoles.length > 0){
					def roleIds = Utils.convertStrings2Longs(selectedRoles)
					println("Role IDs: " + roleIds)
					def roleCriteria = Role.createCriteria()
					def roles = roleCriteria.list{'in'('id', roleIds)}
					userInstance.roles = roles
				}
			}
			if (!userInstance.hasErrors() && userInstance.save(flush: true)) {
				flash.message = "${message(code: 'default.updated.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])}"
				redirect(action: "show", id: userInstance.id)
			}
			else {
				render(view: "edit", model: [userInstance: userInstance])
			}
		}
		else {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
			redirect(action: "list")
		}
		println "<--UserController.update"
	}

	@Privileged(privileges = ['DELETE_USER'])
	def delete = {
		def userInstance = User.get(params.id)
		if(userInstance && userInstance.userName == "admin") {
			flash.message = "Administrator can't be deleted"
			redirect(action: "list")
			return
		}
		if (userInstance) {
			try {
				userInstance.delete(flush: true)
				flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
				redirect(action: "list")
			}
			catch (org.springframework.dao.DataIntegrityViolationException e) {
				flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
				redirect(action: "show", id: params.id)
			}
		}
		else {
			flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])}"
			redirect(action: "list")
		}
	}
}
